package com.architecture.persistence.hibernate;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

import javax.persistence.EntityManager;

import org.hibernate.Criteria;
import org.hibernate.Session;

import com.architecture.entity.Entity;
import com.architecture.util.object.ObjectUtility;

/**
 * <p>Implementation of {@linkplain HibernateDAO}</p>
 * @author JR
 * @param <E>
 */
@SuppressWarnings("unchecked")
public class HibernateDAOImpl<E extends Entity> implements HibernateDAO<E> {

	@Override
	public Collection<E> list() {
		return this.newCriteria().list();
	}

	@Override
	public Collection<E> list(int start, int end) {
		final Criteria criteria = this.newCriteria();
		criteria.setFirstResult(start);
		criteria.setMaxResults(end);
		return criteria.list();
	}
	
	@Override
	public Serializable create(E entity){
		return this.getSession().save(entity);
	}

	@Override
	public E read(Serializable id) {
		return (E)this.getSession().get(getPersistentEntity(), id);
	}

	@Override
	public void update(E entity) {
		this.getSession().update(entity);
	}

	@Override
	public void delete(Serializable id) {
		final E entity = this.read(id);
		if(ObjectUtility.isRef(entity)){
			this.getSession().delete(entity);
		}
	}
	
	public EntityManager getEntityManager(){
		return null;
	}
	
	@Override
	public final Session getSession() {
		return (Session)this.getEntityManager().getDelegate();
	}

	@Override
	public final Criteria newCriteria() {
		return this.getSession().createCriteria(getPersistentEntity());
	}

	@Override
	public final Class<E> getPersistentEntity() {
		final Type type = this.getClass().getGenericSuperclass();
		final ParameterizedType pt = (ParameterizedType) type;
		return (Class<E>)pt.getActualTypeArguments()[0];
	}

}
